1 module hip.component.base; 2 3 interface IComponent 4 { 5 int getID(); 6 string getName(); 7 } 8 9 /** 10 * Adds each of the components to the class. If they contain a mixin template called `ExpandFields`, it will 11 be automatically mixed in. 12 * Params - Components - A list of IBaseComponent implementations 13 * Best Practice: Use `pragma(inline, true)` and `final` if they are a function, as could be a significant difference in the binary 14 * ExpandFields Example : 15 ```d 16 mixin template ExpandFields() ///Expand fields from BodyRectComponent 17 { //Used for convenient access without needing to use _BodyRectComponent.position.x 18 pragma(inline, true) 19 { 20 final ref float x(){ return _BodyRectComponent.position.x; } 21 final ref float y(){ return _BodyRectComponent.position.y; } 22 final ref Vector2 velocity(){ return _BodyRectComponent.velocity; } 23 final ref Vector2 position(){ return _BodyRectComponent.position; } 24 final ref Size size(){ return _BodyRectComponent.size; } 25 } 26 } 27 ``` 28 */ 29 mixin template IncludeComponents(Components...) 30 { 31 static assert(is(typeof(this) : IComponentizable)); 32 private IComponent[] components; 33 static foreach(C; Components) 34 { 35 static assert(is(C : IComponent), C.stringof ~ " is not a component!"); 36 mixin("private C _"~__traits(identifier, C)~";"); 37 38 static if(__traits(compiles, __traits(getMember, C, "ExpandFields"))) 39 mixin C.ExpandFields; 40 } 41 42 void initializeComponents() 43 { 44 static if(is(typeof(super) : IComponentizable)) 45 super.initializeComponents(); 46 static foreach(C; Components) 47 { 48 components~= __traits(getMember, typeof(this), "_"~__traits(identifier, C)) = new C(); 49 } 50 } 51 52 /** 53 * Used more internally in the class. It returns the component in compilation time and gives 54 * a compilation failure if it doesn't exists 55 * Returns: The Component evaluated in compilation time 56 */ 57 T Get(T)() 58 { 59 return mixin("_",__traits(identifier, T)); 60 } 61 IComponent getComponentBase(int id) 62 { 63 foreach(c; components) 64 if(c.getID() == id) 65 return c; 66 return null; 67 } 68 } 69 70 class IBaseComponent(T) : IComponent 71 { 72 final int getID(){return getComponentID!T;} 73 final string getName(){return __traits(identifier, T);} 74 } 75 76 interface IComponentizable 77 { 78 IComponent getComponentBase(int id); 79 T getComponent(T)() if(is(T : IComponent)) {return cast(T)getComponentBase(getComponentID!T);} 80 81 } 82 83 private __gshared int compID = 0; 84 private int getComponentID(T)() 85 { 86 __gshared int _compId = 0; 87 if(_compId == 0) 88 _compId = ++compID; 89 return _compId; 90 }